package com.zlyx.easy.netty.client.core;

import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;

/**
 * @Auth 赵光
 * @Desc easy-netty对外提供方法
 * @Date 2019年4月29日
 */
public abstract class AbstractBaseNettyClient extends ChannelInboundHandlerAdapter{
	
	private static ConcurrentMap<String, Channel> channels = new ConcurrentHashMap<>();
	
	protected class ChannelFactory {

		protected String host;

		protected int port;

		private Bootstrap b;

		public ChannelFactory(AbstractBaseNettyClient client, String host, int port) throws Exception {
			this.host = host;
			this.port = port;
			if (b == null) {
				EventLoopGroup group = new NioEventLoopGroup();
				this.b = new Bootstrap();
				this.b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
						.handler(new ChannelInitializer<SocketChannel>() {
							@Override
							protected void initChannel(SocketChannel socketChannel) throws Exception {
								socketChannel.pipeline().addLast("decoder", new ByteArrayDecoder());
								socketChannel.pipeline().addLast("channelHandler", client);
								socketChannel.pipeline().addLast("encoder", new ByteArrayEncoder());
							}
						});
			}
		}

		public Channel getChannel(String key) {
			Channel channel = channels.get(key);
			if (channel == null || !channel.isActive()) {
				channel = b.connect(new InetSocketAddress(host, port)).channel();
				channels.put(key, channel);
			}
			return channel;
		}
	}
}
